/*
 * Copyright (c) 2023-2024 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.screw.query.phoenix;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.elsfs.cloud.common.util.exception.QueryException;
import org.elsfs.cloud.common.util.lang.Assert;
import org.elsfs.cloud.common.util.lang.ExceptionUtils;
import org.elsfs.cloud.common.util.sql.JdbcUtils;
import org.elsfs.cloud.screw.constant.ScrewConstants;
import org.elsfs.cloud.screw.mapping.Mapping;
import org.elsfs.cloud.screw.metadata.Database;
import org.elsfs.cloud.screw.metadata.PrimaryKey;
import org.elsfs.cloud.screw.query.AbstractDatabaseQuery;
import org.elsfs.cloud.screw.query.phoenix.model.PhoenixColumnModel;
import org.elsfs.cloud.screw.query.phoenix.model.PhoenixPrimaryKeyModel;
import org.elsfs.cloud.screw.query.phoenix.model.PhoenixSqlDatabaseModel;
import org.elsfs.cloud.screw.query.phoenix.model.PhoenixlTableModel;

/**
 * Phoenix数据库查询
 *
 * @author zeng
 */
public class PhoenixDataBaseQuery extends AbstractDatabaseQuery {

  public PhoenixDataBaseQuery(DataSource dataSource) {
    super(dataSource);
  }

  @Override
  public Database getDataBase() throws QueryException {
    PhoenixSqlDatabaseModel model = new PhoenixSqlDatabaseModel();
    model.setDatabase(getCatalog());
    return model;
  }

  @Override
  public List<PhoenixlTableModel> getTables() throws QueryException {
    ResultSet resultSet = null;
    try {
      // 查询
      resultSet =
          getMetaData()
              .getTables("", getSchema(), ScrewConstants.PERCENT_SIGN, new String[] {"TABLE"});
      // 映射
      return Mapping.convertList(resultSet, PhoenixlTableModel.class);
    } catch (SQLException e) {
      throw ExceptionUtils.mpe(e);
    } finally {
      JdbcUtils.close(resultSet);
    }
  }

  @Override
  public List<PhoenixColumnModel> getTableColumns(String table) throws QueryException {
    Assert.notEmpty(table, "Table name can not be empty!");
    ResultSet resultSet = null;
    try {
      // 查询
      resultSet = getMetaData().getColumns("", getSchema(), table, ScrewConstants.PERCENT_SIGN);
      // 映射
      List<PhoenixColumnModel> list = Mapping.convertList(resultSet, PhoenixColumnModel.class);

      // 处理columnName
      list.forEach(model -> model.setColumnType(model.getTypeName()));
      return list;
    } catch (SQLException e) {
      throw ExceptionUtils.mpe(e);
    } finally {
      JdbcUtils.close(resultSet);
    }
  }

  @Override
  public List<PhoenixColumnModel> getTableColumns() throws QueryException {
    return getTableColumns(ScrewConstants.PERCENT_SIGN);
  }

  @Override
  public List<PhoenixPrimaryKeyModel> getPrimaryKeys(String table) throws QueryException {
    ResultSet resultSet = null;
    try {
      // 查询
      resultSet = getMetaData().getPrimaryKeys("", getSchema(), table);
      // 映射
      return Mapping.convertList(resultSet, PhoenixPrimaryKeyModel.class);
    } catch (SQLException e) {
      throw ExceptionUtils.mpe(e);
    } finally {
      JdbcUtils.close(resultSet, this.connection);
    }
  }

  @Override
  public List<? extends PrimaryKey> getPrimaryKeys() throws QueryException {
    ResultSet resultSet = null;
    try {
      // 由于单条循环查询存在性能问题，所以这里通过自定义SQL查询数据库主键信息
      String sql =
          "SELECT '' AS TABLE_CAT, TABLE_SCHEM AS TABLE_SCHEM, TABLE_NAME, COLUMN_NAME AS"
              + " COLUMN_NAME, KEY_SEQ, PK_NAME FROM SYSTEM.\"CATALOG\" WHERE PK_NAME IS NOT NULL"
              + " AND KEY_SEQ IS NOT NULL GROUP BY TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, KEY_SEQ,"
              + " PK_NAME";
      // 拼接参数
      resultSet = prepareStatement(sql).executeQuery();
      return Mapping.convertList(resultSet, PhoenixPrimaryKeyModel.class);
    } catch (SQLException e) {
      throw new QueryException(e);
    } finally {
      JdbcUtils.close(resultSet);
    }
  }

  @Override
  protected String getCatalog() throws QueryException {
    return "phoenix";
  }
}
